package lxs.swift.instance;


import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.function.BiFunction;

public class HashStruct implements StructInstance<String>, Map<String, Object> {
    private final Map<String, Object> object;
    private final Actions<String> actions = new Actions<>(this);

    public HashStruct(Map<String, Object> object) {
        this.object = object;
    }

    public HashStruct(Object o) {
        if (!Types.isObject(o)) throw new RuntimeException(o.getClass().getName() + " cannot to be a HashStruct");
        Object structuring = Types.structuring(o);
        this.object = ((Map<String, Object>) structuring);
    }

    public HashStruct() {
        this.object = new HashMap<>();
    }

    @Override
    public Object of(String key) {
        Objects.requireNonNull(key);
        return this.object.get(key);
    }

    @Override
    public void set(String key, Object value) {
        Objects.requireNonNull(key);
        this.object.put(key, value);
    }

    @Override
    public Object delete(String key) {
        return this.object.remove(key);
    }

    @Override
    public void retains(String... keys) {
        Objects.requireNonNull(keys);
        Set<String> keySet = new HashSet<>(Arrays.asList(keys));
        object.keySet().removeIf(next -> !keySet.contains(next));
    }

    @Override
    public void iterate(BiFunction<String, Object, Boolean> function) {
        for (String key : this.object.keySet()) {
            Boolean apply = function.apply(key, this.object.get(key));
            if (!apply) return;
        }
    }

    @Override
    public Actions<String> action() {
        return actions;
    }

    @Override
    public int size() {
        return this.object.size();
    }

    @Override
    public boolean isEmpty() {
        return this.object.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return this.object.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return this.object.containsValue(value);
    }

    @Override
    public Object get(Object key) {
        return this.object.get(key);
    }

    @Override
    public Object put(String key, Object value) {
        Objects.requireNonNull(key);
        Object structuring = Types.structuring(value);
        return this.object.put(key, structuring);
    }

    @Override
    public Object remove(Object key) {
        return this.object.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ?> m) {
        this.object.putAll(m);
    }

    @Override
    public void clear() {
        this.object.clear();
    }

    @NotNull
    @Override
    public Set<String> keySet() {
        return this.object.keySet();
    }

    @NotNull
    @Override
    public Collection<Object> values() {
        return this.object.values();
    }

    @NotNull
    @Override
    public Set<Entry<String, Object>> entrySet() {
        return this.object.entrySet();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof HashStruct)) return false;
        HashStruct that = (HashStruct) o;
        return Objects.equals(object, that.object);
    }

    @Override
    public int hashCode() {
        return Objects.hash(object);
    }

    @Override
    public String toString() {
        return this.object.toString();
    }
}
